import { CCInteger, _decorator } from 'cc';
import { ActionSpec } from '../Actuators/ActionSpec';

const { ccclass, property } = _decorator;
export enum SpaceType {
	Discrete = 0,
	Continuous = 1,
}

@ccclass('BrainParameters')
export class BrainParameters {
	@property({ type: CCInteger, serializable: true, visible: true, displayName: 'Space Size' })
	private _vectorObservationSize: number = 1;
	get vectorObservationSize(): number {
		return this._vectorObservationSize;
	}
	set vectorObservationSize(value: number) {
		this._vectorObservationSize = value;
	}

	@property({ type: CCInteger, serializable: true, visible: true, range: [1, 50, 1], displayName: 'Stacked Vectors' })
	private _numStackedVectorObservations: number = 1;
	get numStackedVectorObservations(): number {
		return this._numStackedVectorObservations;
	}

	set numStackedVectorObservations(value: number) {
		this._numStackedVectorObservations = value;
	}

    @property({ type: ActionSpec, serializable: true, visible: true, displayName: 'Actions' })
	private _actionSpec: ActionSpec = new ActionSpec(0);
    get actionSpec(): ActionSpec {
		return this._actionSpec;
	}

	set actionSpec(value: ActionSpec) {
		this._actionSpec.numContinuousActions = value.numContinuousActions;
		this._actionSpec.branchSizes = value.branchSizes;
		this.syncDeprecatedActionFields();
	}

	private _vectorActionSize: number[] = [1];
	private _vectorActionDescriptions: string[] = [];
	private _vectorActionSpaceType: SpaceType = SpaceType.Discrete;
	private _hasUpgradedBrainParametersWithActionSpec: boolean = false;


	get vectorActionSize(): number[] {
		return this._vectorActionSize;
	}

	set vectorActionSize(value: number[]) {
		this._vectorActionSize = value;
	}

	get vectorActionDescriptions(): string[] {
		return this._vectorActionDescriptions;
	}

	set vectorActionDescriptions(value: string[]) {
		this._vectorActionDescriptions = value;
	}

	get vectorActionSpaceType(): SpaceType {
		return this._vectorActionSpaceType;
	}

	set vectorActionSpaceType(value: SpaceType) {
		this._vectorActionSpaceType = value;
	}

	get hasUpgradedBrainParametersWithActionSpec(): boolean {
		return this._hasUpgradedBrainParametersWithActionSpec;
	}

	set hasUpgradedBrainParametersWithActionSpec(value: boolean) {
		this._hasUpgradedBrainParametersWithActionSpec = value;
	}

	public clone(): BrainParameters {
		return new BrainParameters();
	}

	private updateToActionSpec(): void {
		if (
			!this._hasUpgradedBrainParametersWithActionSpec &&
			this._actionSpec.numContinuousActions === 0 &&
			this._actionSpec.numDiscreteActions === 0
		) {
			if (this._vectorActionSpaceType === SpaceType.Continuous) {
				this._actionSpec.numContinuousActions = this._vectorActionSize[0];
			}
			if (this._vectorActionSpaceType === SpaceType.Discrete) {
				this._actionSpec.branchSizes = [...this._vectorActionSize];
			}
		}
		this._hasUpgradedBrainParametersWithActionSpec = true;
	}

	private syncDeprecatedActionFields(): void {
		if (this._actionSpec.numContinuousActions === 0) {
			this._vectorActionSize = [...this._actionSpec.branchSizes];
			this._vectorActionSpaceType = SpaceType.Discrete;
		} else if (this._actionSpec.numDiscreteActions === 0) {
			this._vectorActionSize = [this._actionSpec.numContinuousActions];
			this._vectorActionSpaceType = SpaceType.Continuous;
		} else {
			this._vectorActionSize = [];
		}
	}
}
